<!DOCTYPE HTML>
<html>
<head>
  <script type="application/javascript" src="mediaStreamPlayback.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
  "use strict";

  createHTML({
    title: "MediaStream's addTrack() and removeTrack() with getUserMedia streams Test",
    bug: "1103188"
  });

  runTest(() => Promise.resolve()
    .then(() => getUserMedia({audio: true})).then(stream =>
      getUserMedia({video: true}).then(otherStream => {
        info("Test addTrack()ing a video track to an audio-only gUM stream");
        var track = stream.getTracks()[0];
        var otherTrack = otherStream.getTracks()[0];

        stream.addTrack(track);
        checkMediaStreamContains(stream, [track], "Re-added audio");

        stream.addTrack(otherTrack);
        checkMediaStreamContains(stream, [track, otherTrack], "Added video");

        var testElem = createMediaElement('video', 'testAddTrackAudioVideo');
        var playback = new LocalMediaStreamPlayback(testElem, stream);
        return playback.playMedia(false);
    }))
    .then(() => getUserMedia({video: true})).then(stream =>
      getUserMedia({video: true}).then(otherStream => {
        info("Test addTrack()ing a video track to a video-only gUM stream");
        var track = stream.getTracks()[0];
        var otherTrack = otherStream.getTracks()[0];

        stream.addTrack(track);
        checkMediaStreamContains(stream, [track], "Re-added video");

        stream.addTrack(otherTrack);
        checkMediaStreamContains(stream, [track, otherTrack], "Added video");

        var test = createMediaElement('video', 'testAddTrackDoubleVideo');
        var playback = new LocalMediaStreamPlayback(test, stream);
        return playback.playMedia(false);
    }))
    .then(() => getUserMedia({video: true})).then(stream =>
      getUserMedia({video: true}).then(otherStream => {
        info("Test removeTrack() existing and added video tracks from a video-only gUM stream");
        var track = stream.getTracks()[0];
        var otherTrack = otherStream.getTracks()[0];

        stream.removeTrack(otherTrack);
        checkMediaStreamContains(stream, [track], "Removed non-existing video");

        stream.addTrack(otherTrack);
        checkMediaStreamContains(stream, [track, otherTrack], "Added video");

        stream.removeTrack(otherTrack);
        checkMediaStreamContains(stream, [track], "Removed added video");

        stream.removeTrack(otherTrack);
        checkMediaStreamContains(stream, [track], "Re-removed added video");

        stream.removeTrack(track);
        checkMediaStreamContains(stream, [], "Removed original video");

        var elem = createMediaElement('video', 'testRemoveAllVideo');
        var loadeddata = false;
        elem.onloadeddata = () => { loadeddata = true; elem.onloadeddata = null; };
        elem.srcObject = stream;
        elem.play();
        return wait(500).then(() => {
          ok(!loadeddata, "Stream without tracks shall not raise 'loadeddata' on media element");
          elem.pause();
          elem.srcObject = null;
        })
        .then(() => {
          stream.addTrack(track);
          checkMediaStreamContains(stream, [track], "Re-added added-then-removed track");
          var playback = new LocalMediaStreamPlayback(elem, stream);
          return playback.playMedia(false);
        })
        .then(() => otherTrack.stop());
    }))
    .then(() => getUserMedia({ audio: true })).then(audioStream =>
      getUserMedia({ video: true }).then(videoStream => {
        info("Test adding track and removing the original");
        var audioTrack = audioStream.getTracks()[0];
        var videoTrack = videoStream.getTracks()[0];
        videoStream.removeTrack(videoTrack);
        audioStream.addTrack(videoTrack);

        checkMediaStreamContains(videoStream, [], "1, Removed original track");
        checkMediaStreamContains(audioStream, [audioTrack, videoTrack],
                                 "2, Added external track");

        var elem = createMediaElement('video', 'testAddRemoveOriginalTrackVideo');
        var playback = new LocalMediaStreamPlayback(elem, audioStream);
        return playback.playMedia(false);
      }))
    .then(() => getUserMedia({ audio: true, video: true })).then(stream => {
      info("Test removing stopped tracks");
      stream.getTracks().forEach(t => {
        t.stop();
        stream.removeTrack(t);
      });
      checkMediaStreamContains(stream, [], "Removed stopped tracks");
    })
    .then(() => {
      var ac = new AudioContext();

      var osc1k = createOscillatorStream(ac, 1000);
      var audioTrack1k = osc1k.getTracks()[0];

      var osc5k = createOscillatorStream(ac, 5000);
      var audioTrack5k = osc5k.getTracks()[0];

      var osc10k = createOscillatorStream(ac, 10000);
      var audioTrack10k = osc10k.getTracks()[0];

      var stream = osc1k;
      return Promise.resolve().then(() => {
        info("Analysing audio output with original 1k track");
        var analyser = new AudioStreamAnalyser(ac, stream);
        return analyser.waitForAnalysisSuccess(array =>
                 array[analyser.binIndexForFrequency(50)] < 50 &&
                 array[analyser.binIndexForFrequency(1000)] > 200 &&
                 array[analyser.binIndexForFrequency(5000)] < 50 &&
                 array[analyser.binIndexForFrequency(10000)] < 50);
      }).then(() => {
        info("Analysing audio output with removed original 1k track and added 5k track");
        stream.removeTrack(audioTrack1k);
        stream.addTrack(audioTrack5k);
        var analyser = new AudioStreamAnalyser(ac, stream);
        return analyser.waitForAnalysisSuccess(array =>
                 array[analyser.binIndexForFrequency(1000)] < 50 &&
                 array[analyser.binIndexForFrequency(5000)] > 200 &&
                 array[analyser.binIndexForFrequency(10000)] < 50);
      }).then(() => {
        info("Analysing audio output with removed 5k track and added 10k track");
        stream.removeTrack(audioTrack5k);
        stream.addTrack(audioTrack10k);
        var analyser = new AudioStreamAnalyser(ac, stream);
        return analyser.waitForAnalysisSuccess(array =>
                 array[analyser.binIndexForFrequency(1000)] < 50 &&
                 array[analyser.binIndexForFrequency(5000)] < 50 &&
                 array[analyser.binIndexForFrequency(10000)] > 200);
      }).then(() => {
        info("Analysing audio output with re-added 1k, 5k and added 10k tracks");
        stream.addTrack(audioTrack1k);
        stream.addTrack(audioTrack5k);
        var analyser = new AudioStreamAnalyser(ac, stream);
        return analyser.waitForAnalysisSuccess(array =>
                 array[analyser.binIndexForFrequency(50)] < 50 &&
                 array[analyser.binIndexForFrequency(1000)] > 200 &&
                 array[analyser.binIndexForFrequency(2500)] < 50 &&
                 array[analyser.binIndexForFrequency(5000)] > 200 &&
                 array[analyser.binIndexForFrequency(7500)] < 50 &&
                 array[analyser.binIndexForFrequency(10000)] > 200 &&
                 array[analyser.binIndexForFrequency(11000)] < 50);
      });
    }));
</script>
</pre>
</body>
</html>
